home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 85 / CD Temático 40 Febrero 2004.iso / DOS / testdisk / src / ntfs.c < prev    next >
Encoding:
C/C++ Source or Header  |  2004-01-09  |  17.9 KB  |  501 lines

  1. /*
  2.  
  3.     File: ntfs.c
  4.  
  5.     Copyright (C) 1998-2004 Christophe GRENIER <grenier@cgsecurity.org>
  6.   
  7.     This software is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.   
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.   
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.  */
  22. /*define NTFS_DEBUG 1 */
  23.  
  24. #define NTFS_GETU8(p)      (*(const __u8*)(p))
  25. #define NTFS_GETU16(p)     (*(const __u16*)(p))
  26. #define NTFS_GETU32(p)     (*(const __u32*)(p))
  27. #define NTFS_GETU64(p)     (*(const __u64*)(p))
  28.  
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include <ctype.h>
  32. #include "types.h"
  33. #include "common.h"
  34. #include "intrface.h"
  35. #include "ntfs.h"
  36. #include "fnctdsk.h"
  37. #include "lang.h"
  38. static int create_ntfs_boot_sector(t_param_disk *disk_car,const t_diskext *partition, const int part_type, const int interface, const __u8 cluster_size, const __u64 mft_cluster, const __u64 mftbak_cluster, const __s32 clusters_frs, const __s32 clusters_record);
  39. static int dump_ntfs_info(const struct ntfs_boot_sector *ntfs_header);
  40. static int dump_2ntfs_info(const struct ntfs_boot_sector *nh1, const struct ntfs_boot_sector *nh2);
  41.  
  42. static int ntfs_read_MFT(t_param_disk *disk_car, t_diskext *partition, const struct ntfs_boot_sector*ntfs_header,const int my_type,const int debug, const int dump_ind);
  43. static int ntfs_find_mft(t_param_disk *disk_car, t_diskext *partition, const int debug, const int interface);
  44.  
  45. static int ntfs_get_attr(const char *mft_record, const int my_type, t_diskext *partition, const char *end, const int debug, const int dump_ind, const char*file_name_to_find);
  46.  
  47. int check_NTFS(t_param_disk *disk_car,t_diskext *partition,const int debug,const int dump_ind)
  48. {
  49.   unsigned char buffer[SECTOR_SIZE];
  50.   if(disk_car->read(disk_car,1, &buffer, partition->lba)!=0)
  51.   { return 1; }
  52.   if(test_NTFS(disk_car,(struct ntfs_boot_sector*)&buffer,partition,debug,dump_ind)!=0)
  53.     return 1;
  54.   set_NTFS_info(disk_car,(struct ntfs_boot_sector*)&buffer,partition,debug,dump_ind);
  55.   return 0;
  56. }
  57.  
  58. int recover_NTFS(t_param_disk *disk_car, const struct ntfs_boot_sector*ntfs_header,t_diskext *partition,const int debug, const int dump_ind, const int backup)
  59. {
  60.   if(test_NTFS(disk_car,ntfs_header,partition,debug,dump_ind)!=0)
  61.     return 1;
  62.   partition->part_size=le64(ntfs_header->sectors_nbr)+1;
  63.   partition->part_type=(unsigned char)P_NTFS;
  64.   if(backup)
  65.   {
  66.     partition->boot_sector=partition->part_size-1;
  67.     partition->lba-=partition->part_size-1;
  68.   }
  69.   set_NTFS_info(disk_car,ntfs_header,partition,debug,dump_ind);
  70.   return 0;
  71. }
  72.  
  73. int set_NTFS_info(t_param_disk *disk_car, const struct ntfs_boot_sector*ntfs_header,t_diskext *partition,const int debug, const int dump_ind)
  74. {
  75.   partition->name[0]='\0';
  76.   return ntfs_read_MFT(disk_car, partition, ntfs_header,0x60,debug,dump_ind);
  77. }
  78.  
  79. int test_NTFS(const t_param_disk *disk_car,const struct ntfs_boot_sector*ntfs_header, t_diskext *partition,const int debug, const int dump_ind)
  80. {
  81.   const char*buffer=(const char*)ntfs_header;
  82.   if(le16(ntfs_header->marker)==0xAA55)
  83.   {
  84.     if(memcmp(ntfs_header->system_id,"NTFS",4)==0)
  85.     {
  86.       if((ntfs_header->reserved>0) || (ntfs_header->fats>0) ||
  87.       (ntfs_header->dir_entries[0]!=0) || (ntfs_header->dir_entries[1]!=0) ||
  88.       (ntfs_header->sectors[0]!=0) || (ntfs_header->sectors[1]!=0) ||
  89.       (ntfs_header->fat_length!=0) || (ntfs_header->total_sect!=0) || (ntfs_header->cluster_size==0))
  90.     return 1;
  91.       if((debug!=0) || (dump_ind!=0))
  92.       {
  93.     ecrit_rapport("NTFS at %u/%u/%u\n", LBA2cylinder(disk_car,partition->lba),LBA2head(disk_car,partition->lba),LBA2sector(disk_car,partition->lba));
  94.       }
  95.       if((dump_ind!=0)&&(debug!=0))
  96.     dump(stdscr,buffer,SECTOR_SIZE);
  97.       partition->upart_type=UP_NTFS;
  98.       return 0;
  99.     }
  100.   }     /* fin marqueur de fin :)) */
  101.   return 1;
  102. }
  103.  
  104. /* */
  105. static int ntfs_get_attr(const char *mft_record, const int my_type, t_diskext *partition, const char *end, const int debug, const int dump_ind, const char*file_name_to_find)
  106. {
  107.   const char *attr_record;
  108.   int attr_type;
  109.   /* Only check for magic DWORD here, fixup should have happened before */
  110.   if(memcmp(mft_record,"FILE",4)) return 2;    /* NTFS_RECORD_TYPES == magic_FILE ?*/
  111.   if(NTFS_GETU16(mft_record + 0x14)%8!=0)
  112.     return 2;
  113.   if(NTFS_GETU16(mft_record + 0x14)<42)        /* sizeof(MFT_RECORD)>=42 */
  114.     return 2;
  115.   /*    aff_buffer(BUFFER_ADD,"FILE\n"); */
  116.   /*    aff_buffer(BUFFER_ADD,"seq nbr %lu ",NTFS_GETU16(mft_record+0x10)); */
  117.   /*    aff_buffer(BUFFER_ADD,"main MFT record %lu ",NTFS_GETU64(mft_record+0x20)); */
  118.   /* location of first attribute */
  119.   attr_record= mft_record + NTFS_GETU16(mft_record + 0x14);
  120.   while(1)
  121.   {
  122.     /* Resident attributes attr_len>=24(0x18), non resident is bigger */
  123.     unsigned int attr_len;
  124.     if(attr_record+0x18>=end)
  125.     {
  126.       ecrit_rapport("ntfs_get_attr attr_record+0x18>=end\n");
  127.       return 2;
  128.     }
  129.     attr_type=NTFS_GETU32(attr_record);
  130.     if(attr_type==-1) /* attribute list end with type -1 */
  131.       return 0;
  132. /*   ecrit_rapport("attr_type=%x\n",attr_type); */
  133.     attr_len=NTFS_GETU16(attr_record+4);
  134.     if((attr_len%8!=0)||(attr_len<0x18))
  135.     {
  136.       ecrit_rapport("ntfs_get_attr attr_type=%x attr_len=%u (attr_len%%8!0)||(attr_len<0x18)\n",attr_type,attr_len);
  137.       return 2;
  138.     }
  139.     if(dump_ind)
  140.     {
  141.       WINDOW *window=newwin(0,0,0,0);    /* full screen */
  142.       keypad(window, TRUE); /* Need it to get arrow key */
  143.       aff_copy(window);
  144.       dump(window,attr_record,attr_len);
  145.       delwin(window);
  146. #ifdef DJGPP
  147.       wredrawln(stdscr,0,stdscr->_maxy);    /* redrawwin def is boggus in pdcur24 */
  148. #else
  149.       redrawwin(stdscr);    /* stdscr has been corrupted by window */
  150. #endif
  151.     }
  152.     if(NTFS_GETU8(attr_record+8)==0)    /* attribute is resident */
  153.     {
  154.       unsigned int attr_value_length=NTFS_GETU16(attr_record+0x10);
  155.       unsigned int attr_value_offset=NTFS_GETU16(attr_record+0x14);
  156.       const char *attr_list_entry=attr_record+attr_value_offset;
  157.       if(attr_value_offset%8!=0)
  158.       {
  159.     ecrit_rapport("ntfs_get_attr attr_value_offset=%u (%%8!=0)\n",attr_value_offset);
  160.     return 2;
  161.       }
  162.       if(attr_list_entry+26>=end)
  163.       {
  164.     ecrit_rapport("ntfs_get_attr attr_list_entry+26=%p, end=%p\n",attr_list_entry+26,end);
  165.     return 2;
  166.       }
  167.       /* We found the attribute type. Is the name correct, too? */
  168. #ifdef NTFS_DEBUG
  169.       ecrit_rapport("pos=%p type %x attr_list_entry %p\n",attr_record-mft_record,attr_type,attr_list_entry-mft_record);
  170.       aff_buffer(BUFFER_ADD,"type %02X\n",attr_type);
  171. #endif
  172.       if((attr_value_offset+attr_value_length>attr_len) || (attr_list_entry+attr_len >= end))
  173.       {
  174.     ecrit_rapport("ntfs_get_attr ");
  175.     return 2;
  176.       }
  177.       if((attr_type==my_type)&&(attr_value_offset!=0))
  178.       {
  179.     switch(attr_type)
  180.     {
  181.       case 0x30:    /* AT_FILE_NAME */
  182.         {
  183.           const char *file_name_attr=attr_list_entry;
  184.           unsigned int file_name_length;
  185.           const char *name_it;
  186.           if(file_name_attr+0x42>=end)
  187.         return 2;
  188.           file_name_length=NTFS_GETU8(file_name_attr+0x40);    /* size in unicode char */
  189.           if(file_name_attr+0x42+2*file_name_length>=end)
  190.         return 2;
  191.           {
  192.         char file_name[file_name_length+1];
  193.         unsigned int i;
  194.         /*        aff_buffer(BUFFER_ADD,"MFT record nbr %lu ",NTFS_GETU64(file_name_attr)); */
  195.         for(name_it=file_name_attr+0x42,i=0;i<file_name_length; name_it+=2,i++)
  196.           file_name[i]=*name_it;
  197.         file_name[i]='\0';
  198.         if(file_name_to_find!=NULL)
  199.         {
  200.           if(debug)
  201.           {
  202.             ecrit_rapport("file_name=%s, %u\n",file_name,NTFS_GETU32(file_name_attr));
  203.           }
  204.           if(strcmp(file_name_to_find,file_name)==0)
  205.             return 1;
  206.           else
  207.             return 2;
  208.         } else
  209.           aff_buffer(BUFFER_ADD,"%s\n",file_name);
  210.           }
  211.         }
  212.         break;
  213.       case 0x60:    /* AT_VOLUME_NAME */
  214.         {
  215.           unsigned int volume_name_length=attr_value_length;
  216.           const char *name_it;
  217.           char *dest=partition->name;
  218.           volume_name_length/=2;    /* Unicode */
  219.           if(volume_name_length>sizeof(partition->name)-1)
  220.         volume_name_length=sizeof(partition->name)-1;
  221.           for(name_it=attr_list_entry;(volume_name_length>0) && (*name_it!='\0') && (name_it[1]=='\0'); name_it+=2,volume_name_length--)
  222.         *dest++=*name_it;
  223.           *dest++='\0'; /* 27 january 2003: Correct a bug found by Andreas du Plessis-Denz */
  224.         }
  225.         return 1;
  226.     }
  227.       }
  228.     }
  229.     attr_record+=attr_len;
  230.   }
  231. }
  232.  
  233. #ifdef OLD
  234. int dir_ntfs(WINDOW *window,t_param_disk *disk_car,t_diskext *partition)
  235. {
  236.   unsigned char buffer[SECTOR_SIZE];
  237.   int debug=0;
  238.   int dump_ind=0;
  239.   aff_buffer(BUFFER_RESET,"Q");
  240.   wmove(window,5,0);
  241.   aff_part(window,AFF_PART_NL,disk_car,partition);
  242.   ecrit_rapport("\n");
  243.   aff_part_rapport(disk_car,partition);
  244.   if(disk_car->read(disk_car,1, &buffer, partition->lba+partition->boot_sector)!=0)
  245.   { return 1; }
  246.   if(test_NTFS(disk_car,(struct ntfs_boot_sector*)&buffer,partition,debug,dump_ind)!=0)
  247.   {
  248.     aff_buffer(BUFFER_ADD,"Invalid NTFS data\n");
  249.   }
  250.   else
  251.     ntfs_read_MFT(disk_car,partition,(struct ntfs_boot_sector*)&buffer,0x30,0,0);
  252.   aff_buffer(BUFFER_DISPLAY,"Q",window);
  253.   return 0;
  254. }
  255. #endif
  256.  
  257. static int ntfs_read_MFT(t_param_disk *disk_car, t_diskext *partition, const struct ntfs_boot_sector*ntfs_header,const int my_type,const int debug, const int dump_ind)
  258. {
  259.   unsigned char *buffer;
  260.   unsigned char *attr;
  261.   dword mft_pos;
  262.   unsigned int mft_recordsize;
  263.   mft_pos=partition->lba+ntfs_header->reserved+ntfs_header->mft_cluster*ntfs_header->cluster_size;
  264.   if(ntfs_header->clusters_record>0)
  265.     mft_recordsize=ntfs_header->cluster_size*ntfs_header->clusters_record;
  266.   else
  267.     mft_recordsize=1<<(-ntfs_header->clusters_record);
  268.   buffer=(unsigned char *)MALLOC(mft_recordsize*SECTOR_SIZE);
  269. #ifdef NTFS_DEBUG
  270.   ecrit_rapport("NTFS cluster size = %u\n",ntfs_header->cluster_size);
  271.   ecrit_rapport("NTFS MFT_record_size = %u\n",mft_recordsize);
  272.   ecrit_rapport("NTFS MFT cluster = %lu\n",ntfs_header->mft_cluster);
  273. #endif
  274.   if(disk_car->read(disk_car,mft_recordsize, buffer, mft_pos)!=0)
  275.   {
  276.     ecrit_rapport(msg_ROOT_CLUSTER_RERR);
  277.     FREE(buffer);
  278.     return 1;
  279.   }
  280.   attr=buffer;
  281.   while(attr+0x30<=(buffer+mft_recordsize*SECTOR_SIZE))
  282.   {
  283.     int res=ntfs_get_attr(attr,my_type,partition,buffer+mft_recordsize*SECTOR_SIZE,debug,dump_ind,NULL);
  284.     if((res>0)|| (NTFS_GETU32(attr + 0x1C)<0x30))
  285.     {
  286.       FREE(buffer);
  287.       return res;
  288.     }
  289.     attr+= NTFS_GETU32(attr + 0x1C);
  290.   }
  291.   FREE(buffer);
  292.   return 0;
  293. }
  294.  
  295. int is_ntfs(const int part_type)
  296. {
  297.   switch(part_type)
  298.   {
  299.     case P_NTFS:
  300.     case P_NTFSH:
  301.       return 1;
  302.   }
  303.   return 0;
  304. }
  305.  
  306. #ifdef NEW
  307. static int create_ntfs_boot_sector(t_param_disk *disk_car,const t_diskext *partition, const int part_type, const int interface, const __u8 cluster_size, const __u64 mft_cluster, const __u64 mftbak_cluster, const __s32 clusters_frs, const __s32 clusters_record)
  308. {
  309.   unsigned char orgboot[SECTOR_SIZE];
  310.   unsigned char newboot[SECTOR_SIZE];
  311.   struct ntfs_boot_sector *org_ntfs_header=(struct ntfs_boot_sector *)&orgboot;
  312.   struct ntfs_boot_sector *ntfs_header=(struct ntfs_boot_sector *)&newboot;
  313.   int error=0;
  314.   if(disk_car->read(disk_car,1, &orgboot, partition->lba)!=0)
  315.   {
  316.     ecrit_rapport(msg_CHKFAT_RERR); return 1;
  317.   }
  318.   memcpy(&newboot,&orgboot,SECTOR_SIZE);
  319.   memcpy(ntfs_header->system_id,"NTFS    ",8);
  320.   ntfs_header->sector_size[0]=SECTOR_SIZE & 0xFF;
  321.   ntfs_header->sector_size[1]=SECTOR_SIZE>>8;
  322.   ntfs_header->cluster_size=cluster_size;
  323.   ntfs_header->reserved=0;
  324.   ntfs_header->fats=0;
  325.   ntfs_header->dir_entries[0]=0;
  326.   ntfs_header->dir_entries[1]=0;
  327.   ntfs_header->sectors[0]=0;
  328.   ntfs_header->sectors[1]=0;
  329.   ntfs_header->media=0xF8;
  330.   ntfs_header->fat_length=0;
  331.   ntfs_header->secs_track=disk_car->CHS.sector;
  332.   ntfs_header->heads=disk_car->CHS.head+1;
  333.   if(partition->status==STATUS_LOG)
  334.     ntfs_header->hidden=63;
  335.   else
  336.     ntfs_header->hidden=partition->lba;
  337.   ntfs_header->total_sect=0;
  338.   ntfs_header->sectors_nbr=partition->part_size-1;
  339.   ntfs_header->mft_cluster=mft_cluster;
  340.   ntfs_header->mftbak_cluster=mftbak_cluster;
  341.   ntfs_header->clusters_frs=clusters_frs;
  342.   ntfs_header->clusters_record=clusters_record;
  343.   ntfs_header->marker=0xAA55;
  344.   if(memcmp(newboot,orgboot,SECTOR_SIZE))
  345.   {
  346.     ecrit_rapport("             New / Current boot sector");
  347.     dump_2ntfs_rapport(ntfs_header,org_ntfs_header);
  348.     ecrit_rapport("Extrapolated boot sector and current boot sector are different.\n");
  349.   }
  350.   else
  351.   {
  352.     ecrit_rapport("Extrapolated boot sector and current boot sector are identical.\n");
  353.   }
  354.   if(error)
  355.     ecrit_rapport("Bad extrapolation.\n");
  356.   /* */
  357.   if(interface)
  358.   {
  359.     struct MenuItem menuSaveBoot[]=
  360.     {
  361.       { 'Q',"Quit","Quit this section"},
  362.       { 'W', "Write","Write boot"},
  363.       { 0, NULL, NULL }
  364.     };
  365.     const char *options="Q";
  366.     int do_write=0;
  367.     aff_copy(stdscr);
  368.     wmove(stdscr,4,0);
  369.     wdoprintf(stdscr,"%s",disk_car->description(disk_car));
  370.     mvwaddstr(stdscr,6,0,msg_PART_HEADER2);
  371.     wmove(stdscr,7,0);
  372.     aff_part(stdscr,AFF_PART_ORDER,disk_car,partition);
  373.     wmove(stdscr,8,0);
  374.     if(memcmp(newboot,orgboot,SECTOR_SIZE))    /* Only compare the first sector */
  375.     {
  376.       options="WQ";
  377.       dump_2ntfs_info(ntfs_header, org_ntfs_header);
  378.       dump_2ntfs_rapport(ntfs_header, org_ntfs_header);
  379.       wdoprintf(stdscr,"Extrapolated boot sector and current boot sector are different.\n");
  380.       if(error)
  381.     ecrit_rapport("Warning: Extrapolated boot sector have incorrect values.\n");
  382.     }
  383.     else
  384.     {
  385.       dump_ntfs_info(ntfs_header);
  386.       dump_ntfs_rapport(ntfs_header);
  387.       wdoprintf(stdscr,"Extrapolated boot sector and current boot sector are identical.\n");
  388.     }
  389.     switch(toupper(wmenuSelect(stdscr,INTER_DUMP_Y, INTER_DUMP_X, menuSaveBoot,8,options,MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, 0)))
  390.     {
  391.       case 'W':
  392.     if(strchr(options,'W')!=NULL)
  393.       do_write=1;
  394.     break;
  395.     }
  396.     if(do_write!=0 && ask_confirmation("Write new NTFS boot sector, confirm ? (Y/N)")!=0)
  397.     {
  398.       ecrit_rapport("Write new boot!\n");
  399.       /* Write boot sector and backup boot sector */
  400.       if(disk_car->write(disk_car,1, &newboot, partition->lba))
  401.       {
  402.     display_message("Write error: Can't write new NTFS boot sector\n");
  403.       }
  404.       if(disk_car->write(disk_car,1, &newboot, partition->lba+partition->part_size-1)!=0)
  405.       {
  406.     display_message("Write error: Can't write new NTFS backup boot sector\n");
  407.       }
  408.     }
  409.     else
  410.       ecrit_rapport("Don't write new boot!\n");
  411.   }
  412.   return 0;
  413. }
  414. #endif
  415.  
  416. static int dump_2ntfs_info(const struct ntfs_boot_sector *nh1, const struct ntfs_boot_sector *nh2)
  417. {
  418.   wdoprintf(stdscr,"cluster_size    %u %u\n",nh1->cluster_size,nh2->cluster_size);
  419.   wdoprintf(stdscr,"mft_cluster     %lu %lu\n",(long unsigned int)nh1->mft_cluster,(long unsigned int)nh2->mft_cluster);
  420.   wdoprintf(stdscr,"mftbak_cluster  %lu %lu\n",(long unsigned int)nh1->mftbak_cluster,(long unsigned int)nh2->mftbak_cluster);
  421.   wdoprintf(stdscr,"clusters_frs    %d %d\n",nh1->clusters_frs,nh2->clusters_frs);
  422.   wdoprintf(stdscr,"clusters_record %d %d\n",nh1->clusters_record,nh2->clusters_record);
  423.   return 0;
  424. }
  425.  
  426. int dump_2ntfs_rapport(const struct ntfs_boot_sector *nh1, const struct ntfs_boot_sector *nh2)
  427. {
  428.   ecrit_rapport("cluster_size    %u %u\n",nh1->cluster_size,nh2->cluster_size);
  429.   ecrit_rapport("mft_cluster     %lu %lu\n",(long unsigned int)nh1->mft_cluster,(long unsigned int)nh2->mft_cluster);
  430.   ecrit_rapport("mftbak_cluster  %lu %lu\n",(long unsigned int)nh1->mftbak_cluster,(long unsigned int)nh2->mftbak_cluster);
  431.   ecrit_rapport("clusters_frs    %d %d\n",nh1->clusters_frs,nh2->clusters_frs);
  432.   ecrit_rapport("clusters_record %d %d\n",nh1->clusters_record,nh2->clusters_record);
  433.   return 0;
  434. }
  435.  
  436. static int dump_ntfs_info(const struct ntfs_boot_sector *ntfs_header)
  437. {
  438.   wdoprintf(stdscr,"cluster_size    %u\n",ntfs_header->cluster_size);
  439.   wdoprintf(stdscr,"mft_cluster     %lu\n",(long unsigned int)ntfs_header->mft_cluster);
  440.   wdoprintf(stdscr,"mftbak_cluster  %lu\n",(long unsigned int)ntfs_header->mftbak_cluster);
  441.   wdoprintf(stdscr,"clusters_frs    %d\n",ntfs_header->clusters_frs);
  442.   wdoprintf(stdscr,"clusters_record %d\n",ntfs_header->clusters_record);
  443.   return 0;
  444. }
  445.  
  446. int dump_ntfs_rapport(const struct ntfs_boot_sector *ntfs_header)
  447. {
  448.   ecrit_rapport("cluster_size    %u\n",ntfs_header->cluster_size);
  449.   ecrit_rapport("mft_cluster     %lu\n",(long unsigned int)ntfs_header->mft_cluster);
  450.   ecrit_rapport("mftbak_cluster  %lu\n",(long unsigned int)ntfs_header->mftbak_cluster);
  451.   ecrit_rapport("clusters_frs    %d\n",ntfs_header->clusters_frs);
  452.   ecrit_rapport("clusters_record %d\n",ntfs_header->clusters_record);
  453.   return 0;
  454. }
  455.  
  456. static int ntfs_find_mft(t_param_disk *disk_car, t_diskext *partition, const int debug, const int interface)
  457. {
  458.   unsigned long int sector;
  459.   unsigned char buffer[2*SECTOR_SIZE];
  460.   int ind_stop=FALSE;
  461.   for(sector=1;(sector<partition->part_size)&&(ind_stop==FALSE);sector++)
  462.   {
  463.     if((interface!=0) &&(sector%200)==0)
  464.     {
  465.       wmove(stdscr,9,0);
  466.       wclrtoeol(stdscr);
  467.       wdoprintf(stdscr,"Search mft %10lu/%lu",sector,partition->part_size);
  468.       wrefresh(stdscr);
  469.       switch(wgetch_nodelay(stdscr))
  470.       {
  471.     case KEY_ENTER:
  472. #ifdef PADENTER
  473.       case PADENTER:
  474. #endif
  475.     case '\n':
  476.     case '\r':
  477.     case 's':
  478.     case 'S':
  479.       ind_stop=1;
  480.       break;
  481.       }
  482.     }
  483.     if(disk_car->read(disk_car,2, &buffer, partition->lba+sector)!=0)
  484.     { return 1; }
  485.     if(memcmp(buffer,"FILE",4)==0 && (NTFS_GETU16(buffer+ 0x14)%8==0) && (NTFS_GETU16(buffer+ 0x14)>=42))
  486.     {
  487.       int res;
  488.       res=ntfs_get_attr(buffer,0x30,partition,buffer+2*SECTOR_SIZE,debug,0,"$MFT");
  489.       if(res==1)
  490.     ecrit_rapport("mft at %ld, seq=%u, main=%u res=%d\n",sector,NTFS_GETU8(buffer+0x10),NTFS_GETU32(buffer+0x20),res);
  491.     }
  492.   }
  493.   return 0;
  494. }
  495.  
  496. int rebuild_NTFS_BS(t_param_disk *disk_car, t_diskext *partition, const int debug, const int dump_ind,const int interface)
  497. {
  498.   ntfs_find_mft(disk_car,partition,debug,interface);
  499.   return 0;
  500. }
  501.